<!-- 角色信息 -->
<!-- 角色信息 -->
<template>
  <div>
    <el-dialog v-model="dialogVisible" width="400" :title="title" draggable appendToBody destroyOnClose lockScroll :closeOnClickModal="false">
      <el-form ref="elFormRef" v-loading="initLoading" :model="formData" :rules="rules" scrollToError statusIcon>
        <el-form-item label="角色名称" prop="roleName" required labelWidth="6em">
          <el-input v-model="formData.roleName" :minlength="roleNameMin" :maxlength="roleNameMax" placeholder="请输入角色名称" clearable></el-input>
        </el-form-item>
        <el-form-item label="数据范围" labelWidth="6em" prop="dataScope">
          <el-select v-model="formData.dataScope" placeholder="请选择角色数据范围" clearable>
            <el-option v-for="i in dataScopeList" :key="i.value" :label="i.label" :value="i.value"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="备注" prop="remark" labelWidth="6em">
          <el-input
            v-model="formData.remark"
            placeholder="请输入简介"
            :autosize="{ minRows: 2, maxRows: 3 }"
            type="textarea"
            :minlength="remarkMin"
            :maxlength="remarkMax"
            clearable
            showWordLimit
          ></el-input>
        </el-form-item>
        <el-form-item label="访问权限" prop="roleMenuList" labelWidth="6em">
          <el-scrollbar v-if="!isAdmin" :maxHeight="280" noresize>
            <el-tree
              ref="elTreeRef"
              style="width: 284px"
              nodeKey="value"
              :data="routes"
              :props="{ children: 'children', label: 'title' }"
              accordion
              showCheckbox
            ></el-tree>
          </el-scrollbar>
          <el-select v-else modelValue="最高权限" disabled>
            <el-option label="最高权限" value="最高权限"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item labelWidth="0em">
          <div style="width: 100%; padding-top: 20px">
            <el-button style="width: 100%" type="success" :loading="submitLoading" :disabled="submitLoading" :icon="IconPlus" @click="submit">保存</el-button>
          </div>
        </el-form-item>
      </el-form>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
  import IconPlus from '~icons/ep/plus';
  import type { FormInstance, FormRules } from 'element-plus';
  import { type RoleRequest, type SysRole, addRoleAxios, editRoleAxios, getRoleMenuListAxios } from '@/api/permission-management';
  import { returnRouteBasedOnPermissions } from '@/router/router-util';
  import { dataScopeList } from '../data';

  import type { RouteRecordRaw } from 'vue-router';
  import { getFathersById } from '@/utils/common.ts';

  type $AddShowData = {
    type: 'add';
    /** 添加时的回调 */
    addCallBack: () => void;
  };
  type $EditShowData = {
    type: 'edit';
    /** 角色 */
    role: SysRole;
    /** 编辑时的回调 */
    editCallBack: () => void;
  };

  interface Routes {
    title: string;
    value: string;
    children?: Routes[];
  }
  // const routes: Ref<Routes[]> = ref();
  const routes = computed<Routes[]>(() => {
    return getRoutes(returnRouteBasedOnPermissions());
  });
  const elTreeRef: $RefComp<'ElTree'> = ref(null);

  /**
   * 得到路由
   */
  function getRoutes(list: RouteRecordRaw[]): Routes[] {
    return list.map((item) => {
      return {
        title: item.meta?.title || '',
        value: item.path,
        children: item.children ? getRoutes(item.children) : [],
      };
    });
  }

  let addCallBack: $AddShowData['addCallBack'] | undefined = undefined;
  let editCallBack: $EditShowData['editCallBack'] | undefined = undefined;
  const submitLoading = ref(false);
  const initLoading = ref(false);
  const dialogVisible = ref(false);
  const elFormRef: Ref<FormInstance | null> = ref(null);
  const title: Ref<string> = ref('');
  const isAdmin = ref(false);
  const formData: RoleRequest = reactive<RoleRequest>({
    roleId: undefined,
    roleName: '',
    remark: '',
    dataScope: '',
    roleMenuList: [],
  });
  const remarkMin = 0;
  const remarkMax = 100;
  const roleNameMin = 2;
  const roleNameMax = 10;

  const rules = computed<FormRules>(() => {
    const _rules: FormRules = {
      roleName: [
        { required: true, type: 'string', message: '请输入角色名称', trigger: ['blur', 'change'] },
        { min: roleNameMin, max: roleNameMax, type: 'string', message: ` 角色名称只能输入${roleNameMin}-${roleNameMax}个字符`, trigger: ['blur', 'change'] },
      ],
      remark: [{ min: remarkMin, max: remarkMax, type: 'string', message: `备注只能输入${remarkMin}-${remarkMax}个字符`, trigger: ['blur', 'change'] }],
      dataScope: [{ required: true, type: 'string', message: '请选择数据范围', trigger: ['blur', 'change'] }],
    };
    if (!isAdmin.value) {
      _rules.roleMenuList = [{ required: true, type: 'array', message: '请勾选访问权限', trigger: ['blur', 'change'] }];
    }

    return _rules;
  });

  /**
   * 显示
   */
  async function show(data: $AddShowData | $EditShowData) {
    formData.remark = '';
    formData.roleName = '';
    formData.dataScope = '';
    formData.roleMenuList = [];
    editCallBack = 'editCallBack' in data && typeof data.editCallBack === 'function' ? data.editCallBack : undefined;
    addCallBack = 'addCallBack' in data && typeof data.addCallBack === 'function' ? data.addCallBack : undefined;
    title.value = data.type === 'edit' ? '编辑角色' : '新增角色';
    dialogVisible.value = true;
    if (data.type === 'edit' && typeof data.role) {
      formData.roleId = data.role.roleId;
      formData.roleName = data.role.roleName;
      formData.dataScope = data.role.dataScope;
      formData.remark = data.role.remark;
      isAdmin.value = data.role.admin;
      if (!isAdmin.value) {
        try {
          initLoading.value = true;
          const res = await getRoleMenuListAxios(formData.roleId);
          initLoading.value = false;
          const keys = res.data.filter((item) => item.menuType === 'M').map((item) => item.path);
          elTreeRef.value?.setCheckedKeys(keys);
        } catch (error) {
          initLoading.value = false;
          ElToast.error(error.msg || '获取权限信息失败');
        }
      }
    } else {
      isAdmin.value = false;
      formData.roleName = '';
      formData.remark = '';
      formData.roleId = undefined;
    }
  }

  /**
   * 隐藏
   */
  function hide() {
    dialogVisible.value = false;
  }

  /** 提交 */
  async function submit() {
    const _roleMenuList: (number | string)[] | undefined = elTreeRef.value?.getCheckedKeys();
    formData.roleMenuList = [];
    if (_roleMenuList) {
      for (const roleMenuListElement of _roleMenuList) {
        const val = getFathersById(roleMenuListElement, routes.value, 'value', 'value', 'children');
        for (let i = 0, len = val.length; i < len; i++) {
          if (formData.roleMenuList.every((v) => v.path !== val[i])) {
            formData.roleMenuList.push({ menuType: i === len - 1 ? 'M' : 'N', path: val[i] });
          }
        }
      }
    }
    // formData.roleMenuList = _roleMenuList?.map((item) => ({ menuType: 'M', path: item })) as RoleMenuPermission[];

    try {
      await elFormRef.value?.validate();
    } catch (error) {
      ElToast.error('提交失败，请完善表单，-BD002');
      return;
    }
    try {
      submitLoading.value = true;
      if (formData.roleId) {
        await editRoleAxios(formData);
        typeof editCallBack === 'function' && editCallBack();
      } else {
        await addRoleAxios(formData);
        typeof addCallBack === 'function' && addCallBack();
      }
      ElToast.success('提交成功');
      submitLoading.value = false;
      hide();
    } catch (error) {
      submitLoading.value = false;
      ElToast.error(error.msg || '提交失败，-BD003');
    }
  }

  defineExpose({ show, hide });
</script>
